package com.hanxiaozhang.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;


/**
 * 〈一句话功能简述〉<br>
 * 〈〉
 *
 * @author hanxinghua
 * @create 2022/4/28
 * @since 1.0.0
 */
@Slf4j
@EnableAsync
@Configuration
public class ThreadPoolConfig {


    @Value("${async.executor.core-pool-size:10}")
    private int corePoolSize;

    @Value("${async.executor.max-pool-size:10}")
    private int maxPoolSize;

    @Value("${async.executor.queue-capacity:10}")
    private int queueCapacity;

    @Value("${async.executor.await-termination-seconds:60}")
    private int awaitTerminationSeconds;

    @Value("${async.executor.wait-for-tasks-to-complete-on-shutdown:true}")
    private boolean waitForTasksToCompleteOnShutdown;

    /**
     * 创建线程池
     */
    @Bean(name = "asyncExecutor")
    public ThreadPoolTaskExecutor asyncExecutor() {
        return initExecutor("asyncExecutor");
    }


    private ThreadPoolTaskExecutor initExecutor(String threadNamePrefix) {
        ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
        //设置核心线程数
        threadPool.setCorePoolSize(corePoolSize);
        //设置最大线程数
        threadPool.setMaxPoolSize(maxPoolSize);
        //线程池所使用的缓冲队列
        threadPool.setQueueCapacity(queueCapacity);
        //等待任务在关机时完成--表明等待所有线程执行完
        threadPool.setWaitForTasksToCompleteOnShutdown(waitForTasksToCompleteOnShutdown);
        // 等待时间 （默认为0，此时立即停止），并没等待xx秒后强制停止
        threadPool.setAwaitTerminationSeconds(awaitTerminationSeconds);
        // 线程名称前缀
        threadPool.setThreadNamePrefix(threadNamePrefix);
        // 线程池拒绝策略：
        // ABORT（缺省）：抛出TaskRejectedException异常，然后不执行
        // DISCARD：不执行，也不抛出异常即放弃该线程
        // DISCARD_OLDEST：丢弃queue中最旧的那个任务
        // CALLER_RUNS：不在新线程中执行任务，而是由调用者所在的线程来执行(不再异步,即交给主线程执行该任务)，但是如果主线程已经结束，则任务会被拒绝
        threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 初始化线程
        threadPool.initialize();

        return threadPool;
    }

}
